package com.apchernykh.rozhlasapp.services;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.apchernykh.ceskyrozhlas.basic.R;
import com.apchernykh.rozhlasapp.RozhlasAppActivity;
import com.apchernykh.rozhlasapp.utils.ConditionalLog;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.widget.RemoteViews;

public abstract class NotifiedService extends Service
{

	@Override
	public void onCreate() {
		onCreateApi4Workaround();
		super.onCreate();
	}
	
	protected static final int ONGOING_NOTIFICATION = 1;
	public static final String ACTION_PLAYBACK_STOP = "com.apchernykh.rozhlasapp.PLAYBACK_STOP";
	public static final String ACTION_PLAYBACK_START = "com.apchernykh.rozhlasapp.PLAYBACK_START";
	public static final String ACTION_PLAYBACK_KEEPALIVE = "com.apchernykh.rozhlasapp.PLAYBACK_KEEPALIVE";
	public boolean mBackgroundEnabled = false;

	public static PendingIntent createBackgroundPlaybackControlIntent(Context iContext, boolean iStart) {
		Intent playbackControlIntent = new Intent(iContext,
				BackgroundPlaybackService.class);
		playbackControlIntent.setAction(iStart?ACTION_PLAYBACK_START:ACTION_PLAYBACK_STOP);
		ConditionalLog.e(playbackControlIntent.toString());
		return PendingIntent.getService(iContext.getApplicationContext(), 0, playbackControlIntent, PendingIntent.FLAG_UPDATE_CURRENT);
	}

	public static PendingIntent createKeepaliveIntent(Context iContext) {
		Intent playbackControlIntent = new Intent(iContext,
				BackgroundPlaybackService.class);
		playbackControlIntent.setAction(ACTION_PLAYBACK_KEEPALIVE);
		ConditionalLog.e(playbackControlIntent.toString());
		return PendingIntent.getService(iContext.getApplicationContext(), 0, playbackControlIntent, PendingIntent.FLAG_UPDATE_CURRENT);
	}
	
	public void setNotification(String aSummary, String aPlayingNow) {
		mBackgroundEnabled = true;
		NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder(
				this);
		RemoteViews aCustomLayoutRemoteView = new RemoteViews(getPackageName(),
				R.layout.notification_background);
		aCustomLayoutRemoteView.setTextViewText(R.id.notif_playingNow,
				aPlayingNow);
		aCustomLayoutRemoteView.setTextViewText(R.id.notif_summary, aSummary);
		aCustomLayoutRemoteView.setOnClickPendingIntent(
				R.id.notif_stop_background, createBackgroundPlaybackControlIntent(this, false));
		mNotificationBuilder.setSmallIcon(R.drawable.ic_cro_logo_big);
	
		// if (android.os.Build.VERSION.SDK_INT <
		// android.os.Build.VERSION_CODES.HONEYCOMB) {
		// // prior to 11 one cannot click on the button in notification. So,
		// // the whole notification will be dedicated to stoppinng playback.
		// mNotificationBuilder
		// .setContentIntent(createStopBackgroundIntent(this));
		// } else {
		// Intent notificationIntent = new Intent(getApplicationContext(),
		// RozhlasAppActivity.class);
		// PendingIntent aPendingIntent = PendingIntent.getActivity(this, 0,
		// notificationIntent, 0);
		// mNotificationBuilder.setContentIntent(aPendingIntent);
		// }
	
		Intent aNotificationIntent = new Intent(getApplicationContext(),
				RozhlasAppActivity.class);
		PendingIntent aPendingIntent = PendingIntent.getActivity(this, 0,
				aNotificationIntent, 0);
		mNotificationBuilder.setContentIntent(aPendingIntent);
	
		// This is a hack over the bug in notifications prior to HoneyComb.
		// Namely, setContent() always resets to default layout
		Notification aTaskbarNotification = mNotificationBuilder.build();
		aTaskbarNotification.contentView = aCustomLayoutRemoteView;
	
		startForegroundCompat(ONGOING_NOTIFICATION, aTaskbarNotification);
	}

	private static final Class<?>[] mSetForegroundSignature = new Class[] { boolean.class };
	private static final Class<?>[] mStartForegroundSignature = new Class[] {
				int.class, Notification.class };
	private static final Class<?>[] mStopForegroundSignature = new Class[] { boolean.class };
	private NotificationManager mNM;
	private Method mSetForeground;
	private Method mStartForeground;
	private Method mStopForeground;
	private Object[] mSetForegroundArgs = new Object[1];
	private Object[] mStartForegroundArgs = new Object[2];
	private Object[] mStopForegroundArgs = new Object[1];

	void invokeMethod(Method iMethod, Object[] iArgs) {
		try {
			iMethod.invoke(this, iArgs);
		} catch (InvocationTargetException e) {
			// Should not happen.
			ConditionalLog.e("Unable to invoke method", e);
		} catch (IllegalAccessException e) {
			// Should not happen.
			ConditionalLog.e("Unable to invoke method", e);
		}
	}

	/**
	 * This is a wrapper around the new startForeground method, using the older
	 * APIs if it is not available.
	 */
	void startForegroundCompat(int iId, Notification iNotification) {
		// If we have the new startForeground API, then use it.
		if (mStartForeground != null) {
			mStartForegroundArgs[0] = Integer.valueOf(iId);
			mStartForegroundArgs[1] = iNotification;
			invokeMethod(mStartForeground, mStartForegroundArgs);
			return;
		}
	
		// Fall back on the old API.
		mSetForegroundArgs[0] = Boolean.TRUE;
		invokeMethod(mSetForeground, mSetForegroundArgs);
		mNM.notify(iId, iNotification);
	}

	@Override
	public void onDestroy() {
		stopForegroundCompat(ONGOING_NOTIFICATION);
		super.onDestroy();
	}
	
	/**
	 * This is a wrapper around the new stopForeground method, using the older
	 * APIs if it is not available.
	 */
	protected void stopForegroundCompat(int iId) {
		mBackgroundEnabled = false;
		// If we have the new stopForeground API, then use it.
		if (mStopForeground != null) {
			mStopForegroundArgs[0] = Boolean.TRUE;
			invokeMethod(mStopForeground, mStopForegroundArgs);
			return;
		}
	
		// Fall back on the old API. Note to cancel BEFORE changing the
		// foreground state, since we could be killed at that point.
		mNM.cancel(iId);
		mSetForegroundArgs[0] = Boolean.FALSE;
		invokeMethod(mSetForeground, mSetForegroundArgs);
	}

	private void onCreateApi4Workaround() {
		mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		try {
			mStartForeground = getClass().getMethod("startForeground",
					mStartForegroundSignature);
			mStopForeground = getClass().getMethod("stopForeground",
					mStopForegroundSignature);
			return;
		} catch (NoSuchMethodException e) {
			// Running on an older platform.
			mStartForeground = mStopForeground = null;
		}
		try {
			mSetForeground = getClass().getMethod("setForeground",
					mSetForegroundSignature);
		} catch (NoSuchMethodException e) {
			throw new IllegalStateException(
					"OS doesn't have Service.startForeground OR Service.setForeground!");
		}
	}
	
}